package com.ruoyi.file.service.storage.impl.minio;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.file.domain.SysStorageConfig;
import com.ruoyi.file.enums.StorageTypeEnum;
import com.ruoyi.file.service.storage.base.BaseS3StorageServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.awscore.exception.AwsServiceException;

/**
 * MinIO存储服务实现
 * MinIO使用bucket policy来管理权限，而不是标准的S3 ACL
 * 
 * @author ruoyi
 */
@Slf4j
@Service("minioStorageService")
public class MinioStorageServiceImpl extends BaseS3StorageServiceImpl {

    @Override
    protected StorageTypeEnum getStorageType() {
        return StorageTypeEnum.MINIO;
    }

    @Override
    public boolean shouldUsePathStyle() {
        return true; // MinIO 使用路径风格
    }

    @Override
    protected boolean shouldSetContentType() {
        return false; // MinIO 不设置content-type以避免签名不匹配
    }

    @Override
    public boolean setBucketPermission(String bucketName, String permission, SysStorageConfig config) {
        try (S3Client s3Client = createS3Client(config)) {
            if ("private".equalsIgnoreCase(permission)) {
                // 对于private权限，删除bucket policy
                try {
                    DeleteBucketPolicyRequest deleteBucketPolicyRequest = DeleteBucketPolicyRequest.builder()
                            .bucket(bucketName)
                            .build();
                    s3Client.deleteBucketPolicy(deleteBucketPolicyRequest);
                    log.info("删除MinIO存储桶policy，设置为私有: {}", bucketName);
                } catch (AwsServiceException e) {
                    // 如果没有policy或者其他错误，说明已经是私有的了
                    if (e.statusCode() == 404) {
                        log.info("MinIO存储桶 {} 已经是私有权限", bucketName);
                    } else {
                        log.warn("删除MinIO存储桶policy时出错: {}", e.getMessage());
                    }
                }
            } else {
                // 对于public权限，设置bucket policy
                String bucketPolicy = generateMinIoBucketPolicy(bucketName, permission);
                
                PutBucketPolicyRequest putBucketPolicyRequest = PutBucketPolicyRequest.builder()
                        .bucket(bucketName)
                        .policy(bucketPolicy)
                        .build();
                
                s3Client.putBucketPolicy(putBucketPolicyRequest);
            }
            return true;
        } catch (Exception e) {
            log.error("设置MinIO存储桶权限失败: {}", e.getMessage(), e);
            throw new ServiceException("设置存储桶权限失败: " + e.getMessage());
        }
    }

    @Override
    public String getBucketPermission(String bucketName, SysStorageConfig config) {
        try (S3Client s3Client = createS3Client(config)) {
            GetBucketPolicyRequest getBucketPolicyRequest = GetBucketPolicyRequest.builder()
                    .bucket(bucketName)
                    .build();
            
            GetBucketPolicyResponse response = s3Client.getBucketPolicy(getBucketPolicyRequest);
            String policy = response.policy();
            
            // 解析bucket policy来确定权限
            return parseMinioBucketPolicy(policy);
        } catch (AwsServiceException e) {
            // 没有bucket policy意味着是私有的
            if (e.statusCode() == 404) {
                return "private";
            } else {
                log.error("获取MinIO存储桶权限失败: {}", e.getMessage(), e);
                return "unknown";
            }
        } catch (Exception e) {
            log.error("获取MinIO存储桶权限失败: {}", e.getMessage(), e);
            return "unknown";
        }
    }

    /**
     * 生成MinIO bucket policy
     */
    private String generateMinIoBucketPolicy(String bucketName, String permission) {
        return switch (permission.toLowerCase()) {
            case "public-read" -> String.format("""
                    {
                        "Version": "2012-10-17",
                        "Statement": [
                            {
                                "Effect": "Allow",
                                "Principal": "*",
                                "Action": [
                                    "s3:GetObject"
                                ],
                                "Resource": [
                                    "arn:aws:s3:::%s/*"
                                ]
                            }
                        ]
                    }
                    """, bucketName);
            case "public-read-write" -> String.format("""
                    {
                        "Version": "2012-10-17",
                        "Statement": [
                            {
                                "Effect": "Allow",
                                "Principal": "*",
                                "Action": [
                                    "s3:GetObject",
                                    "s3:PutObject",
                                    "s3:DeleteObject"
                                ],
                                "Resource": [
                                    "arn:aws:s3:::%s/*"
                                ]
                            },
                            {
                                "Effect": "Allow",
                                "Principal": "*",
                                "Action": [
                                    "s3:ListBucket"
                                ],
                                "Resource": [
                                    "arn:aws:s3:::%s"
                                ]
                            }
                        ]
                    }
                    """, bucketName, bucketName);
            default -> throw new ServiceException("不支持的权限类型: " + permission);
        };
    }

    /**
     * 解析MinIO bucket policy
     */
    private String parseMinioBucketPolicy(String policy) {
        if (policy == null || policy.isEmpty()) {
            return "private";
        }
        
        // 简单的策略解析
        if (policy.contains("s3:GetObject") && policy.contains("s3:PutObject")) {
            return "public-read-write";
        } else if (policy.contains("s3:GetObject")) {
            return "public-read";
        } else {
            return "private";
        }
    }

    @Override
    public String getBucketCors(String bucketName, SysStorageConfig config) {
        // MinIO的bucket policy本身就支持跨域访问
        // 当bucket设置为public权限时，实际上已经允许了跨域访问
        try {
            String permission = getBucketPermission(bucketName, config);
            if ("public-read".equals(permission) || "public-read-write".equals(permission)) {
                return "CORS已通过Bucket Policy配置 - MinIO公共桶自动支持跨域访问";
            } else if ("private".equals(permission)) {
                return "未配置CORS - 私有桶不支持跨域访问，请设置为公共权限";
            } else {
                return "未知权限状态";
            }
        } catch (Exception e) {
            log.warn("获取MinIO存储桶权限失败: {}", e.getMessage());
            return "获取CORS状态失败: " + e.getMessage();
        }
    }

    @Override
    public boolean configureBucketCors(String bucketName, SysStorageConfig config) {
        // MinIO通过bucket policy来实现跨域访问
        // 直接设置为public-read-write权限即可支持跨域
        try {
            return setBucketPermission(bucketName, "public-read-write", config);
        } catch (Exception e) {
            log.error("MinIO配置CORS失败: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean deleteBucketCors(String bucketName, SysStorageConfig config) {
        // MinIO删除CORS配置就是设置为private权限
        try {
            return setBucketPermission(bucketName, "private", config);
        } catch (Exception e) {
            log.error("MinIO删除CORS失败: {}", e.getMessage(), e);
            return false;
        }
    }
}
